home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / st80_r41.lha / st80_r41 / latex.st < prev    next >
Text File  |  1993-07-23  |  14KB  |  431 lines

  1. "       NAME           latex.st
  2.         AUTHOR         Carl McConnell <mcconnel@cs.uiuc.edu>
  3.         FUNCTION       print out Smalltalk source as LaTeX source
  4.         ST-VERSIONS    4.1
  5.         PREREQUISITES  none
  6.         DISTRIBUTION   world
  7.         VERSION        1.0
  8.         DATE           April 7, 1993
  9.  
  10. This code adds a 'print LaTeX on...' choice to the menus in the various browser panes.  When selected, this menu choice produces a file containing a LaTeX version of the Smalltalk source for the selected item.  LaTeXing categories and classes yields self-contained LaTeX documents; LaTeXing protocols and methods yields output meant for inclusion in a LaTeX document.  In particular, LaTeXing a category yields a document with a table of contents showing what page the class definitions are on, and so the resulting file needs to be latex'd twice.
  11.  
  12.         Carl McConnell
  13.         mcconnel@cs.uiuc.edu
  14.         Department of Computer Science
  15.         University of Illinois at Urbana-Champaign
  16. "!
  17.  
  18.  
  19. !Filename methodsFor: 'stream creation'!
  20.  
  21. latexStream
  22.     "Answer a write stream connected to the file represented by
  23.     the receiver."
  24.  
  25.     ^LatexStream on: (FileConnection
  26.             openFileNamed: self
  27.             mode: #writeOnly
  28.             creationRule: #truncateOrCreate)! !
  29.  
  30.  
  31. !Browser methodsFor: 'category list'!
  32.  
  33. categoryMenu
  34.     "Answer a Menu of operations on class categories to be 
  35.     displayed when the operate menu button is pressed."
  36.     "Browser flushMenus"
  37.  
  38.     category == nil ifTrue: [^PopUpMenu
  39.             labels: 'add...\update\edit all\find class...' withCRs
  40.             lines: #(1 3 )
  41.             values: #(#addCategory #updateCategories #editCategories #findClass )].
  42.     CategoryMenu == nil ifTrue: [CategoryMenu := PopUpMenu
  43.                     labels: 'file out as...\print LaTeX on...\hardcopy\spawn\add...\rename as...\remove...\update\edit all\find class...' withCRs
  44.                     lines: #(4 7 9 )
  45.                     values: #(#fileOutCategory #latexOutCategory #printOutCategory #spawnCategory #addCategory #renameCategory #removeCategory #updateCategories #editCategories #findClass )].
  46.     ^CategoryMenu! !
  47.  
  48. !Browser methodsFor: 'class list'!
  49.  
  50. classMenu
  51.     "Answer a Menu of operations on classes that is to be displayed 
  52.     when the operate menu button is pressed."
  53.     "Browser flushMenus"
  54.  
  55.     className == nil ifTrue: [^nil].
  56.     ClassMenu == nil ifTrue: [ClassMenu := PopUpMenu
  57.                     labels: 'file out as...\print LaTeX on...\hardcopy\spawn\spawn hierarchy
  58. hierarchy\definition\comment
  59. inst var refs...\class var refs...\class refs
  60. move to...\rename as...\remove...' withCRs
  61.                     lines: #(5 8 11)
  62.                     values: #(#fileOutClass #latexOutClass #printOutClass #spawnClass #spawnHierarchy #showHierarchy #editClass #editComment #browseFieldReferences #browseClassVariables #browseClassReferences #changeClassCategory #renameClass #removeClass )].
  63.     ^ClassMenu! !
  64.  
  65. !Browser methodsFor: 'protocol list'!
  66.  
  67. protocolMenu
  68.     "Answer a Menu of operations on message categories to be 
  69.     displayed when the operate menu button is pressed."
  70.  
  71.     "Browser flushMenus"
  72.     protocol == nil ifTrue:
  73.         [^ PopUpMenu labels: 'add...\edit all\find method...' withCRs
  74.             lines: #(1)
  75.             values: #(addProtocol #editProtocols #findMethodAndSelectAlphabetic)].
  76.     ProtocolMenu == nil ifTrue:
  77.         [ProtocolMenu := PopUpMenu
  78.             labels: 'file out as...\print LaTeX on...\hardcopy\spawn\add...\rename as...\remove...\edit all\find method...' withCRs
  79.             lines: #(4 7)
  80.             values: #(fileOutProtocol latexOutProtocol printOutProtocol spawnProtocol addProtocol renameProtocol removeProtocol #editProtocols #findMethodAndSelectAlphabetic)].
  81.     ^ ProtocolMenu! !
  82.  
  83. !Browser methodsFor: 'selector list'!
  84.  
  85. selectorMenu
  86.     "Answer a Menu of operations on message selectors to be 
  87.     displayed when the operate menu button is pressed."
  88.  
  89.     "Browser flushMenus"
  90.     selector == nil ifTrue: [^ nil].
  91.     MessageMenu == nil ifTrue:
  92.         [MessageMenu := PopUpMenu
  93.             labels: 'file out as...\print LaTeX on...\hardcopy\spawn\senders\implementors\messages...\move to...\remove...' withCRs
  94.             lines: #(4 7)
  95.             values: #(fileOutMessage latexOutMessage printOutMessage spawnMethod browseSenders browseImplementors browseMessages moveMethod removeMethod)].
  96.     ^ MessageMenu! !
  97.  
  98. !Browser methodsFor: 'private-category functions'!
  99.  
  100. latexOutCategory 
  101.     organization latexOutCategory: category! !
  102.  
  103. !Browser methodsFor: 'private-class functions'!
  104.  
  105. latexOutClass 
  106.     self nonMetaClass latexOut! !
  107.  
  108. !Browser methodsFor: 'private-protocol functions'!
  109.  
  110. latexOutProtocol 
  111.     self selectedClass latexOutProtocol: protocol! !
  112.  
  113. !Browser methodsFor: 'private-selector functions'!
  114.  
  115. latexOutMessage 
  116.     self selectedClass latexOutMessage: selector! !
  117.  
  118.  
  119. !SystemOrganizer methodsFor: 'fileIn/Out'!
  120.  
  121. latexOutCategory: category 
  122.     LatexStream for: category do: 
  123.         [:fileStream | 
  124.         Transcript cr; show: 'Printing ', category, ' on ' , fileStream name.
  125.         fileStream beginCategory: category.
  126.         self latexOutCategory: category on: fileStream.
  127.         fileStream endCategory]!
  128.  
  129. latexOutCategory: category on: aFileStream 
  130.     | firstTrip |
  131.     firstTrip := true.
  132.     (self superclassOrder: category)
  133.         do: 
  134.             [:class | 
  135.             "The test prevents a blank page from being printed right after 
  136.              the table of contents."
  137.             firstTrip
  138.                 ifTrue: [firstTrip := false]
  139.                 ifFalse: [aFileStream anotherClass].
  140.             Transcript crtab; show: class name.
  141.             class latexOutOn: aFileStream]! !
  142.  
  143.  
  144. !ClassDescription methodsFor: 'fileIn/Out'!
  145.  
  146. definitionAsTable
  147.     | table |
  148.     table := OrderedCollection new.
  149.     table add: (Association key: 'class name' value: self name).
  150.     table add: (Association key: 'superclass' value: (superclass == nil
  151.                 ifTrue: ['']
  152.                 ifFalse: [superclass name])).
  153.     table add: (Association key: 'instance variable names' value: self instanceVariablesString).
  154.     table add: (Association key: 'class variable names' value: self classVariablesString).
  155.     table add: (Association key: 'pool dictionaries' value: self sharedPoolsString).
  156.     table add: (Association key: 'category' value: self category asString).
  157.     ^table!
  158.  
  159. latexOutMessage: aString 
  160.     LatexStream for: self name , '-' , aString do: [:fileStream | self latexOutMethodChunk: aString on: fileStream]!
  161.  
  162. latexOutMethodChunk: aSelector on: aFileStream 
  163.     | source parser length |
  164.     Cursor write
  165.         showWhile: 
  166.             [source := (self sourceMethodAt: aSelector) asString.
  167.             (parser := self parserClass new) parseSelector: source.
  168.             length := parser endOfLastToken min: source size.
  169.             ["The parser counts subsequent white space as part of a 
  170.             token, so we subtract the length of that white space."
  171.             (source at: length) isSeparator]
  172.                 whileTrue: [length := length - 1].
  173.             aFileStream printMethod: (source copyFrom: 1 to: length)
  174.                 withBody: (source copyFrom: length + 1 to: source size)]!
  175.  
  176. latexOutOn: aFileStream 
  177.     aFileStream printClassDefinitionFor: self name from: self definitionAsTable.
  178.     aFileStream printClassComment: self comment.
  179.     self organization categories do: 
  180.         [:heading |
  181.         aFileStream anotherProtocol.
  182.         self latexOutProtocol: heading on: aFileStream]!
  183.  
  184. latexOutProtocol: aString 
  185.     LatexStream for: self name , '-' , aString do: [:fileStream | self latexOutProtocol: aString on: fileStream]!
  186.  
  187. latexOutProtocol: aString on: aFileStream 
  188.     self latexOutProtocolChunk: aString on: aFileStream.
  189.     (self organization listAtCategoryNamed: aString)
  190.         do: 
  191.             [:sel | 
  192.             aFileStream anotherMethod.
  193.             self latexOutMethodChunk: sel on: aFileStream]!
  194.  
  195. latexOutProtocolChunk: aString on: aFileStream 
  196.     aFileStream printProtocolHeader: aString! !
  197.  
  198.  
  199. !Metaclass methodsFor: 'accessing'!
  200.  
  201. category
  202.     ^thisClass category! !
  203.  
  204.  
  205. !Class methodsFor: 'fileIn/Out'!
  206.  
  207. latexOut
  208.     LatexStream for: self name do: 
  209.         [:fileStream | 
  210.         Transcript cr; show: 'Printing ', self name, ' on ', fileStream name.
  211.         fileStream beginClass.
  212.         self latexOutOn: fileStream.
  213.         fileStream endClass]!
  214.  
  215. latexOutOn: aFileStream 
  216.     super latexOutOn: aFileStream.
  217.     self class nonTrivial
  218.         ifTrue: 
  219.             [aFileStream anotherClass.
  220.             self class latexOutOn: aFileStream]! !
  221.  
  222. ExternalWriteStream subclass: #LatexStream
  223.     instanceVariableNames: 'generateTableOfContents '
  224.     classVariableNames: 'CharacterMap '
  225.     poolDictionaries: ''
  226.     category: 'OS-Streaming'!
  227. LatexStream comment:
  228. 'I translate Smalltalk into LaTeX.
  229.  
  230. Author:
  231.     Carl McConnell
  232.     mcconnel@cs.uiuc.edu
  233.     Department of Computer Science
  234.     University of Illinois at Urbana-Champaign
  235.     5/90'!
  236.  
  237.  
  238. !LatexStream methodsFor: 'beginning/ending'!
  239.  
  240. beginCategory: category 
  241.     self generateTableOfContents: true.
  242.     self beginDocument.
  243.     self line: '\title{{\bf ', category, '}}'.
  244.     self line: '\author{', self version, '}'.
  245.     self line: '\date{' , Date today printString , ' ' , Time now printString , '}'.
  246.     self line: '\maketitle'.
  247.     self line: '\pagenumbering{roman}'.
  248.     self line: '\setcounter{page}{1}'.
  249.     self line: '\tableofcontents'.
  250.     self line: '\clearpage'.
  251.     self line: '\pagenumbering{arabic}'.
  252.     self line: '\setcounter{page}{1}'.
  253.     self line: '%'!
  254.  
  255. beginClass
  256.     self beginDocument.
  257.     self blankLines: 3!
  258.  
  259. endCategory
  260.     self endDocument!
  261.  
  262. endClass
  263.     self endDocument! !
  264.  
  265. !LatexStream methodsFor: 'printing'!
  266.  
  267. printClassComment: aString 
  268.     aString isEmpty ifTrue: [^self].
  269.     self blankLines: 1.
  270.     self beginFont: '\it'.
  271.     self printSmalltalkString: aString.
  272.     self endFont; cr!
  273.  
  274. printClassDefinitionFor: aString from: aTable 
  275.     self line: '\begin{center}'.
  276.     self beginFont: '\Large \bf'.
  277.     self nextPutAll: aString.
  278.     self endFont; cr.
  279.     self line: '\end{center}'.
  280.     self blankLines: 3.
  281.     self line: '\markright{{\bf ' , aString , '} \hfill}'.
  282.     self generateTableOfContents ifTrue: [self line: '\addcontentsline{toc}{section}{' , aString , '}'].
  283.     self line: '\begin{tabular}{ll}'.
  284.     aTable do: 
  285.         [:assoc | 
  286.         self nextPutAll: assoc key.
  287.         self nextPutAll: '    & '.
  288.         assoc value isEmpty
  289.             ifTrue: [self beginFont: '\it'; nextPutAll: 'none'; endFont]
  290.             ifFalse: [self nextPutAll: '\parbox[t]{4.0in}{\raggedright '; beginFont: '\bf'; nextPutAll: assoc value; endFont; nextPut: $}].
  291.         assoc = aTable last
  292.             ifTrue: [self cr]
  293.             ifFalse: [self line: ' \\']].
  294.     self line: '\end{tabular}'!
  295.  
  296. printMethod: aSelector withBody: aString 
  297.     self beginFont: '\bf'; printSmalltalkString: aSelector; endFont.
  298.     self cr; line: '\nopagebreak'.
  299.     self printSmalltalkString: aString.
  300.     self cr!
  301.  
  302. printProtocolHeader: aString 
  303.     self beginFont: '\sl'.
  304.     self nextPutAll: 'Protocol for '; nextPutAll: aString.
  305.     self endFont; cr.
  306.     self line: '\nopagebreak'! !
  307.  
  308. !LatexStream methodsFor: 'separating'!
  309.  
  310. anotherClass
  311.     self line: '%'.
  312.     self line: '\clearpage'!
  313.  
  314. anotherMethod
  315.     self blankLines: 2!
  316.  
  317. anotherProtocol
  318.     self blankLines: 3! !
  319.  
  320. !LatexStream methodsFor: 'private'!
  321.  
  322. blankLines: n 
  323.     self cr.
  324.     self nextPutAll: '\addvspace{'; print: n; nextPutAll: 'ex}'; cr.
  325.     self line: '\noindent'!
  326.  
  327. generateTableOfContents
  328.     ^generateTableOfContents isNil ifTrue: [false] ifFalse: [generateTableOfContents]!
  329.  
  330. generateTableOfContents: aBoolean
  331.     generateTableOfContents := aBoolean!
  332.  
  333. line: aString
  334.     self nextPutAll: aString; cr!
  335.  
  336. version
  337.     "The version name contains a backslash, hence this hack."
  338.  
  339.     ^Smalltalk version copyReplaceAll: '\' with: '$\backslash$'! !
  340.  
  341. !LatexStream methodsFor: 'private-printing'!
  342.  
  343. printSmalltalkString: aString 
  344.     | output inComment |
  345.     inComment := false.
  346.     aString
  347.         do: 
  348.             [:aCharacter | 
  349.             output := CharacterMap at: aCharacter asInteger.
  350.             output notNil
  351.                 ifTrue: [self nextPutAll: output]
  352.                 ifFalse: ["This character requires special handling."
  353.                     aCharacter = $"
  354.                         ifTrue: 
  355.                             [inComment
  356.                                 ifTrue: [self nextPutAll: ''''''; endFont]
  357.                                 ifFalse: [self beginFont: '\it'; nextPutAll: '``'].
  358.                             inComment := inComment not]
  359.                         ifFalse: [self error: 'unrecognized special character']]]! !
  360.  
  361. !LatexStream methodsFor: 'private-beginning/ending'!
  362.  
  363. beginDocument
  364.     self line: '\documentstyle[11pt]{report}'.
  365.     self line: '\oddsidemargin 0in \evensidemargin 0in'.
  366.     self line: '\marginparwidth 0in \marginparsep 0in'.
  367.     self line: '\topmargin 0in \topskip 0in'.
  368.     self line: '\headheight 0.25in \headsep 0.25in'.
  369.     self line: '\footheight 0in \footskip 0.25in'.
  370.     self line: '\textheight 8.25in \textwidth 6.5in'.
  371.     self line: '\raggedbottom \sloppy'.
  372.     self line: '\pagestyle{myheadings}'.
  373.     self line: '%'.
  374.     self line: '\begin{document}'!
  375.  
  376. beginFont: aString
  377.     self nextPut: ${.
  378.     self nextPutAll: aString; space!
  379.  
  380. endDocument
  381.     self line: '\end{document}'!
  382.  
  383. endFont
  384.     self nextPut: $}! !
  385. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  386.  
  387. LatexStream class
  388.     instanceVariableNames: ''!
  389.  
  390.  
  391. !LatexStream class methodsFor: 'class initialization'!
  392.  
  393. at: aCharacter put: anObject
  394.     CharacterMap at: aCharacter asInteger put: anObject.
  395.     ^anObject!
  396.  
  397. initialize
  398.     "Initialize the table for mapping characters to LaTeX. Characters 
  399.     for which special (or no) action is to be taken have nil entries.
  400.      We won't have to handle NUL characters, so the table size is 127."
  401.  
  402.     CharacterMap := Array new: 127.
  403.     1 to: CharacterMap size 
  404.         do: [:i | CharacterMap at: i put: (String with: (Character value: i))].
  405.     "Characters requiring special handling are mapped to nil."
  406.     self at: $" put: nil.
  407.     self at: Character cr put: (' \\$' replaceAll: $$ with: Character cr).
  408.     self at: Character tab put: '\hspace*{4ex} '.
  409.     #($# $$ $% $& ${ $}) do: [:ch | self at: ch put: (String with: $\ with: ch)].
  410.     #($| $> $< $+ $- $/ $* $@) do: [:ch | self at: ch put: (String with: $$ with: ch with: $$)].
  411.     self at: $~ put: '{\char126}'.
  412.     self at: $^ put: '{\char94}'.
  413.     self at: $\ put: '$\backslash$'! !
  414.  
  415. !LatexStream class methodsFor: 'instance creation'!
  416.  
  417. for: aString do: aBlock 
  418.     | fileName fileStream |
  419.     fileName := DialogView
  420.             requestFileName: 'Print LaTeX on'
  421.             default: (Filename defaultClass suggest: (Filename defaultClass filterSeps: aString, '.tex')). 
  422.     fileName = '' ifTrue: [^nil].
  423.     fileStream :=  fileName asFilename latexStream.
  424.     [aBlock value: fileStream]
  425.         valueNowOrOnUnwindDo: [fileStream close]! !
  426.  
  427. LatexStream initialize!
  428.  
  429. Browser flushMenus!
  430.  
  431.